﻿using FastBuild.TimeJob;
using Wechat_PublicNumber.Common;
using Wechat_PublicNumber.Entity;
using Wechat_PublicNumber.Repository;

namespace Wechat_PublicNumber.Jobs
{
    /// <summary>
    /// 获取所有股票信息
    /// </summary>
    [SkipWhileExecuting]
    public class AllStockInfoJob : DataAccess, IJob
    {
        [Autowired]
        private CommonHttpInvoke _commonHttpInvoke;

        [Autowired]
        private WxTemplateRepository _templateRepository;

        [Autowired]
        private WxHttpInvoke _wxHttpInvoke;

        public async Task Execute()
        {
#if RELEASE
                //非股票交易时间
                if (!StockTime.OpeningQuotation)
                    return;
#endif

            _logger.Info($"AllStockInfoJob Starting execution", "AllStockInfoJob");

            await WXDb.Ado.ExecuteCommandAsync("truncate table StockDetail");

            var industry = await _commonHttpInvoke.GetStockIndustry("cn");

            //循环行业
            foreach (var industries in industry.industries)
            {
                var page = 1;
                var count = 90;
                //循环获取股票详情
                while (count >= 90)
                {
                    var stockInfo = await _commonHttpInvoke.GetStockDecline(page, ind_code: industries.encode);

                    count = stockInfo.list.Count;

                    var list = stockInfo.list.Where(item => item.symbol.StartsWith("SH60") || item.symbol.StartsWith("SZ00") || item.symbol.StartsWith("SZ30")).Select(item => new StockDetail()
                    {
                        symbol = item.symbol,
                        name = item.name,
                        percent = decimal.TryParse(item.percent, out var percent) ? percent : 0,
                        chg = decimal.TryParse(item.chg, out var chg) ? chg : 0,
                        current = decimal.TryParse(item.current, out var current) ? current : 0,
                        current_year_percent = decimal.TryParse(item.current_year_percent, out var current_year_percent) ? current_year_percent : 0,
                        turnover_rate = decimal.TryParse(item.turnover_rate, out var turnover_rate) ? turnover_rate : 0,
                        industries = industries.name,
                        market_capital = (int)(item.market_capital / 100000000)
                    }).ToList();

                    foreach (var item in list)
                    {
                        item.pe_ttm = await _commonHttpInvoke.Getpe_ttm(item.symbol);

                        var dayK = await _commonHttpInvoke.GetStockDayK(item.symbol, 60, new DateTimeOffset(DateTime.Now.AddDays(1)).ToUnixTimeMilliseconds());

                        #region 连续下跌天数和下跌幅度
                        var percentList = dayK.item.Select(d => decimal.Parse(d[7])).Reverse().ToList();
                        var pricetList = dayK.item.Select(d => decimal.Parse(d[5])).Reverse().ToList();

                        var continuous_decline_days = 0;
                        foreach (var percent in percentList)
                        {
                            if (percent < 0)
                                continuous_decline_days++;
                            else if (percent < 2) { }
                            else
                                break;
                        }
                        if (continuous_decline_days > 1)
                        {
                            pricetList = pricetList.Take(continuous_decline_days).Reverse().ToList();
                            item.continuous_decline_days = continuous_decline_days;
                            item.continuous_decline_percent = Math.Round((pricetList.Last() - pricetList.First()) / pricetList.First() * 100, 2);
                        }
                        #endregion

                        #region 2-10日涨跌幅
                        List<List<string>> last11 = dayK.item;

                        if (dayK.item.Count > 11)
                            last11 = dayK.item.Skip(dayK.item.Count - 11).Take(11).ToList();

                        item.last_2_percent = GetPercentByIndex(8, last11);

                        item.last_3_percent = GetPercentByIndex(7, last11);

                        item.last_4_percent = GetPercentByIndex(6, last11);

                        item.last_5_percent = GetPercentByIndex(5, last11);

                        item.last_6_percent = GetPercentByIndex(4, last11);

                        item.last_7_percent = GetPercentByIndex(3, last11);

                        item.last_8_percent = GetPercentByIndex(2, last11);

                        item.last_9_percent = GetPercentByIndex(1, last11);

                        item.last_10_percent = GetPercentByIndex(0, last11);
                        #endregion

                        await Task.Delay(50);
                    }

                    if (list.Count > 0)
                        await WXDb.Insertable(list).ExecuteCommandAsync();

                    page++;
                }
            }

            var allList = await WXDb.Queryable<StockDetail>().ToListAsync();

            var rate10List = allList.Where(s => s.turnover_rate > 8).ToList();

            var stockDetailList = new List<StockDetail>();

            AddDeclineStockDetail(rate10List.OrderBy(s => s.last_2_percent).Take(5).ToList(), stockDetailList, 2);
            AddDeclineStockDetail(rate10List.OrderBy(s => s.last_3_percent).Take(5).ToList(), stockDetailList, 3);
            AddDeclineStockDetail(rate10List.OrderBy(s => s.last_4_percent).Take(5).ToList(), stockDetailList, 4);
            AddDeclineStockDetail(rate10List.OrderBy(s => s.last_5_percent).Take(5).ToList(), stockDetailList, 5);
            AddDeclineStockDetail(rate10List.OrderBy(s => s.last_6_percent).Take(5).ToList(), stockDetailList, 6);
            AddDeclineStockDetail(rate10List.OrderBy(s => s.last_7_percent).Take(5).ToList(), stockDetailList, 7);
            AddDeclineStockDetail(rate10List.OrderBy(s => s.last_8_percent).Take(5).ToList(), stockDetailList, 8);
            AddDeclineStockDetail(rate10List.OrderBy(s => s.last_9_percent).Take(5).ToList(), stockDetailList, 9);
            AddDeclineStockDetail(rate10List.OrderBy(s => s.last_10_percent).Take(5).ToList(), stockDetailList, 10);

            await WXDb.Updateable(stockDetailList).UpdateColumns(s => new { s.count, s.status }).ExecuteCommandAsync();

            _logger.Info($"AllStockInfoJob Successfully executed", "AllStockInfoJob");
        }

        public void AddDeclineStockDetail(List<StockDetail> list, List<StockDetail> list1, int status)
        {
            foreach (var item in list)
            {
                if (list1.Any(s => s.ID == item.ID))
                    list1.First(s => s.ID == item.ID).count++;
                else
                    list1.Add(new StockDetail()
                    {
                        ID = item.ID,
                        count = 1,
                        status = status
                    });
            }
        }

        public decimal GetPercentByIndex(int startindex, List<List<string>> list)
        {
            if (list == null || list.Count == 0 || startindex >= list.Count)
                return 0;

            var startPrice = decimal.Parse(list[startindex][5]);
            var endPrice = decimal.Parse(list[list.Count - 1][5]);
            //保留两位小数
            return Math.Round((endPrice - startPrice) / startPrice * 100, 2);
        }
    }

    public class StockDayK
    {
        public string symbol { get; set; }

        public List<string> item { get; set; }
    }
}
